
package com.hlkj.pay.app.merchant.ext.impl.heepay.ext;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import cn.hutool.core.codec.Base64Encoder;
import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.framework.extension.annotation.Extension;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelPayOrderContext;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelPayOrderQueryContext;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelRefundPayOrderContext;
import com.hlkj.pay.app.merchant.ext.impl.heepay.HeePayScenePayOrderExtPt;
import com.hlkj.pay.app.merchant.ext.impl.heepay.constanct.HeePayConstant;
import com.hlkj.pay.app.merchant.ext.impl.heepay.constanct.HeePayExtConstant;
import com.hlkj.pay.app.merchant.ext.impl.heepay.dto.HeePayAppChannelParams;
import com.hlkj.pay.app.merchant.ext.impl.heepay.dto.HeePayConfig;
import com.hlkj.pay.app.merchant.ext.impl.heepay.dto.HeePayOrderSubmitRes;
import com.hlkj.pay.app.merchant.ext.impl.heepay.handler.HeePayMerchantCommonParamsHandle;
import com.hlkj.pay.app.merchant.ext.impl.helipay.constant.HeliPayConstant;
import com.hlkj.pay.enums.MerchantEnum;
import com.hlkj.pay.enums.PayEnums;
import com.hlkj.pay.enums.PayOrderEnums;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAccessAuthDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppChannelDO;
import com.hlkj.pay.infrastructure.model.order.PayOrderDO;
import com.hlkj.pay.infrastructure.model.pay.PayWayDO;
import com.hlkj.pay.util.DateUtils;
import com.hlkj.pay.util.MerchantUtils;
import com.hlkj.pay.vo.order.req.PayOrderCommonParamReq;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * 支付宝支付，商户扫用户二维码收款
 * 
 * @author HlpayTeam
 * @date 2024/11/18 13:08
 */
@Slf4j
@Repository
@RequiredArgsConstructor
@Extension(bizId = HeePayExtConstant.ALIPAY)
public class HeePayAlipayPayOrderExtPt extends HeePaySceneCommonPayOrder implements HeePayScenePayOrderExtPt {

    @Autowired
    private HeePayMerchantCommonParamsHandle heePayMerchantCommonParamsHandle;

    @Override
    public void submitChannelPayOrder(ChannelPayOrderContext channelPayOrderContext) {
        // 配置转换
        CommonResult<HeePayConfig> commonResult = heePayMerchantCommonParamsHandle.heePayConfig(channelPayOrderContext.getProviderChannelConfigDO(),
                channelPayOrderContext.isTest());
        HeePayConfig heePayConfig = commonResult.getData();

        PayOrderDO payOrderDO = channelPayOrderContext.getPayOrderDO();
        MerchantAppChannelDO merchantAppChannelDO = channelPayOrderContext.getMerchantAppChannelDO();
        HeePayAppChannelParams heliPayAppChannelParams = heePayMerchantCommonParamsHandle.heePayAppChannelParams(merchantAppChannelDO,heePayConfig);
        PayWayDO payWayDO = channelPayOrderContext.getPayWayDO();
        try {
            Map<String, String> params = new HashMap<>();
            params.put("version", "1");
            params.put("pay_type", "22");
            params.put("agent_id", heePayConfig.getAgentId());
            if(!MerchantEnum.APP_CHANNEL_TYPE.MERCHANT_COMMON.getCode().equals(merchantAppChannelDO.getType())){
                params.put("ref_agent_id", heliPayAppChannelParams.getHeePayId());
            }
            params.put("agent_bill_id", payOrderDO.getPayOrderNo());
            params.put("agent_bill_time", DateUtils.dateToString(System.currentTimeMillis(), "yyyyMMddHHmmss"));
            params.put("pay_amt", MerchantUtils.bigDecimalToString2(payOrderDO.getAmount()));
            params.put("notify_url", channelPayOrderContext.getNotifyUrl());
            params.put("return_url", channelPayOrderContext.getRedirectUrl());
            params.put("user_ip", payOrderDO.getClientIp());
            params.put("goods_name", heePayMerchantCommonParamsHandle.subject(payOrderDO.getSubject()));
            params.put("goods_num", "1");
            params.put("remark", "");
            params.put("expire_time", expireMinute(payOrderDO.getExpiredTime()));
            boolean acct = false;
            if (!PayOrderEnums.FUND_PROCESS_TYPE.NO.getCode().equals(payOrderDO.getFundProcessType())) {
                acct = true;
            }
            if (acct) {
                params.put("meta_option", Base64Encoder.encode("{\"is_guarantee\":\"1\"}"));
            }
            PayEnums.SCENE_PAY_TYPE scenePayType = PayEnums.SCENE_PAY_TYPE.fromByType(payWayDO.getSubType());
            PayOrderCommonParamReq.Extra extra = JsonUtils.parseObject(payOrderDO.getExtra(), PayOrderCommonParamReq.Extra.class);
            switch (scenePayType) {
                case QR:
                    break;
                case WAP:
                case H5:
                    params.put("is_phone", "1");
                    break;
                case MINI_APP:
                    if (!StringUtils.hasText(extra.getUserId())) {
                        channelPayOrderContext.setRemark("汇付宝 支付宝支付请求失败,必须传递支付宝账户或者user_id");
                        channelPayOrderContext.setProcessStatus(Boolean.FALSE);
                        return;
                    }
                    params.put("remark", extra.getUserId());
                    params.put("is_phone", "1");
                    params.put("is_frame", "1");
                    if (acct) {
                        params.put("meta_option", Base64Encoder.encode("{\"is_minipg\":\"1\",\"is_guarantee\":\"1\"}"));
                    }
                    else {
                        params.put("meta_option", Base64Encoder.encode("{\"is_minipg\":\"1\"}"));
                    }
                    break;
                default:
                    channelPayOrderContext.setRemark("汇付宝 支付宝支付请求失败,当前支付不支持" + scenePayType.getDesc());
                    channelPayOrderContext.setProcessStatus(Boolean.FALSE);
                    return;
            }

            String autCode = payOrderDO.getAutCode();
            if (StringUtils.hasText(autCode)) {
                MerchantAccessAuthDO merchantAccessAuthDO = heePayMerchantCommonParamsHandle.getAuthDo(autCode);
                if (merchantAccessAuthDO == null) {
                    params.put("bank_id", "");
                } else params.put("bank_id", merchantAccessAuthDO.getSerialCode());
            }

            log.info("汇付宝 支付宝支付 请求参数:{}", JsonUtils.toJsonString(params));
            CommonResult<String> resultResult = heePayMerchantCommonParamsHandle.heePayOrderRequest(HeePayConstant.PAY_ORDER_SUBMIT_URL, heePayConfig, params,
                    HeePayConstant.PAY_ORDER_SUBMIT_FIELD);
            log.info("汇付宝 支付宝支付 返回参数:{}", JsonUtils.toJsonString(resultResult));
            if (!resultResult.isSuccess()) {
                channelPayOrderContext.setRemark("汇付宝支付宝支付请求失败,失败信息:" + resultResult.getMsg());
                channelPayOrderContext.setProcessStatus(Boolean.FALSE);
                return;
            }
            switch (scenePayType) {
                case MINI_APP:
                    channelPayOrderContext.setPayDataType("data");
                    channelPayOrderContext.setPayInfo(resultResult.getData());
                    return;
                default:
            }
            String response = resultResult.getData();
            HeePayOrderSubmitRes heePayOrderSubmitRes = JsonUtils.parseObject(response, HeePayOrderSubmitRes.class);
            if (HeliPayConstant.REQUEST_SUCCESS.equals(heePayOrderSubmitRes.getCode())) {
                // channelPayOrderContext.setChannelOrderId(heePayOrderCommonRes.get());
                // channelPayOrderContext.setInsOrderNo(heePayOrderCommonRes.getRt16_outTransactionOrderId());
                channelPayOrderContext.setPayDataType("url");
                channelPayOrderContext.setPayInfo(heePayOrderSubmitRes.getQr_code_url());
            }
            else {
                channelPayOrderContext.setProcessStatus(Boolean.FALSE);
                if (StringUtils.hasText(heePayOrderSubmitRes.getMessage())) {
                    channelPayOrderContext.setRemark(heePayOrderSubmitRes.getMessage());
                }
                else {
                    channelPayOrderContext.setRemark("汇付宝提交支付宝支付返回错误信息为空,错误码为:" + heePayOrderSubmitRes.getCode());
                }
            }

        }
        catch (Exception e) {
            e.printStackTrace();
            log.error("汇付宝提交支付宝支付请求失败 message:{}", e.getMessage(), e);
            channelPayOrderContext.setRemark("汇付宝提交支付宝支付请求失败,失败信息" + e.getMessage());
            channelPayOrderContext.setProcessStatus(Boolean.FALSE);
            // channelMerchantAccessQueryContext.setAccessStatus(MerchantEnum.CHANNEL_CONFIG_STATUS.APPROVE_REFUSE);
        }
    }

    @Override
    public void queryChannelPayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        commonQueryChannelPayOrder(channelPayOrderQueryContext);
    }

    @Override
    public void closeChannelPayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        commonCloseChannelPayOrder(channelPayOrderQueryContext);
    }

    @Override
    public void queryChannelClosePayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        commonQueryChannelClosePayOrder(channelPayOrderQueryContext);
    }

    @Override
    public void refundChannelPayOrder(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        commonRefundChannelPayOrder(channelRefundPayOrderContext);
    }

    @Override
    public void queryRefundChannelPayOrder(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        commonQueryRefundChannelPayOrder(channelRefundPayOrderContext);
    }

    @Override
    public boolean refundApply(ChannelRefundPayOrderContext channelRefundPayOrderContext) {
        return true;
    }

    @Override
    public CommonResult<String> channelOrderCode(ChannelPayOrderContext channelPayOrderContext) {
        return CommonResult.success();
    }
}
